<?php
class MissionHandler {
	public static function getStateAtTime($iMission, $iTiming) {
		try {
			$oQuery = DataHandler::query("
				SELECT
					mission_id,
					timing,
					actiontype,
					stat_todo,
					stat_group_id,
					stat_urgency_id,
					stat_finishtime,
					stat_status,
					stat_users
				FROM
					missionlog
				WHERE
					mission_id = ?
					AND timing < ?
				ORDER BY
					timing DESC
				LIMIT 1
			", $iMission, $iTiming);

			$oRow = $oQuery->fetch(PDO::FETCH_ASSOC);
			$oEntity = array(
				'mission_id' => $oRow['mission_id'],
				'timing' => $oRow['timing'],
				'actiontype' => $oRow['actiontype'],
				'todo' => $oRow['stat_todo'],
				'group_id' => $oRow['stat_group_id'],
				'urgency_id' => $oRow['stat_urgency_id'],
				'finishtime' => $oRow['stat_finishtime'],
				'status' => $oRow['stat_status'],
				'users' => $oRow['stat_users'],
			);
			return $oEntity;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function getFiles($iMission) {
		try {
			if (is_array(@$GLOBALS['mission']['files'][$iMission])) {
				return $GLOBALS['mission']['files'][$iMission];
			}

			$oQuery = DataHandler::query("
				SELECT file_id
				FROM missions_files
				WHERE mission_id = ?
			", $iMission);

			$GLOBALS['mission']['files'][$iMission] = array();
			while (list($iFile) = $oQuery->fetch(PDO::FETCH_NUM)) {
				array_push($GLOBALS['mission']['files'][$iMission], $iFile);
			}
			
			return $GLOBALS['mission']['files'][$iMission];
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function changeUrgency($iJob, $iMission, $iUrgency) {
		try {
			DataHandler::query("
				UPDATE missions
				SET urgency_id = ?
				WHERE job_id = ?
				AND id = ?
			", $iUrgency, $iJob, $iMission);

			$oMissionQuery = DataHandler::query("
				SELECT
					todo,
					group_id,
					status,
					finishtime,
					users
				FROM missions
				WHERE id = ?
			", $iMission);

			list($sTodo, $iGroup, $iStatus, $iFinishTime, $sUsers) = $oMissionQuery->fetch(PDO::FETCH_NUM);

			DataHandler::query("
				INSERT INTO missionlog (
					mission_id,
					timing,
					user_id,
					actiontype,
					stat_todo,
					stat_group_id,
					stat_urgency_id,
					stat_finishtime,
					stat_users,
					stat_status
				) VALUES (
					?,?,?,?,?,?,?,?,?,?
				)
			",
				$iMission,
				thisSecond(),
				$_SESSION['rid'],
				'change',
				addslashes($sTodo),
				$iGroup,
				$iUrgency,
				$iFinishTime,
				$sUsers,
				$iStatus
			);

			return 1;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function rush($iJob, $iMission, $sMessage, $iUsers, $sType)
	{
		try {
			if (!is_array($iUsers) || count($iUsers) == 0)
			{
				throw new MiJobException('At least one user must be selected');
			}

			$oMission = MissionHandler::getMission($iJob, $iMission);
			$oNotes = $oMission->getNotes();
			$oUsers = UserHandler::getUsers();
			$oJobs = JobHandler::getJobs();
			$oJob = $oJobs[$iJob];
			$sStatuses = MissionHandler::getStatuses();

			$sSubject = '['.cAppName.'] '.($sType == 'hurry' ? '�minning' : 'Fyrirspurn').' � verkefninu "'.$oJob->sName.'"';

			$sBody = "";
			if (strlen($sMessage) > 0)
			{
				$sBody .= $oUsers[$_SESSION['rid']]->sUser.": ".$sMessage."\n\n";
			}
			$sBody .= "Verk: ".$oMission->sTodo."\n";
			$sBody .= "Sta�a: ".$sStatuses[$oMission->iStatus]['caption']."\n";
			$sBody .= "Mikilv�gi: ".$oJob->sUrgencies[$oMission->iUrgency]."\n";
			$sBody .= "Verkefni: ".$oJob->sName."\n\n";
			$sBody .= "*** GL�SUR ***\n";
			foreach ($oNotes as $oThisNote)
			{
				$sBody .= coolDate($oThisNote->iTiming)."\n";
				$sBody .= $oUsers[$oThisNote->iUser]->sUser." (".$oUsers[$oThisNote->iUser]->sEmail."):\n";
				$sBody .= stripslashes(trim($oThisNote->sBody))."\n";
				$sBody .= "--------------------------\n";
			}

			$oUsers = UserHandler::getUsers();
			$sToString = '';
			$bFirst = true;
			foreach ($iUsers as $iThisUser)
			{
				$sToString .= (!$bFirst ? ', ' : '').$oUsers[$iThisUser]->sEmail;
				$bFirst = false;
			}
			mail($sToString, $sSubject, $sBody, mailHeaders());

			return 1;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function changeJob($iMission, $iNewJob)
	{
		try {
			// -1 = Unknown SQL error.
			DataHandler::query("
				UPDATE missions
				SET
					job_id = ?,
					group_id = 0
				WHERE id = ?
			", $iNewJob, $iMission);

			DataHandler::query("
				UPDATE notes
				SET job_id = ?
				WHERE mission_id = ?
			", $iNewJob, $iMission);
			
			return 1;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}

	public static function changeMissionTodo($iJob, $iMission, $sTodo)
	{
		try {
			DataHandler::query("
				UPDATE missions
				SET todo = ?
				WHERE
					id = ?
					AND job_id = ?
			", $sTodo, $iMission, $iJob);

			return 1;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function changeMissionStatus($iJob, $iMission, $iStatus)
	{
		
		DataHandler::beginTransaction();
		
		try {
			// -1 = Unknown SQL error.
			DataHandler::query("
				UPDATE missions
				SET status = ?
				WHERE id = ?
			", $iStatus, $iMission);

			$oMissionQuery = DataHandler::query("
				SELECT
					todo,
					group_id,
					urgency_id,
					finishtime,
					users
				FROM missions
				WHERE id = ?
			", $iMission);

			list($sTodo, $iGroup, $iUrgency, $iFinishTime, $sUsers) = $oMissionQuery->fetch(PDO::FETCH_NUM);

			DataHandler::query("
				INSERT INTO missionlog (
					mission_id,
					timing,
					user_id,
					actiontype,
					stat_todo,
					stat_group_id,
					stat_urgency_id,
					stat_finishtime,
					stat_users,
					stat_status
				) VALUES (
					?,?,?,?,?,?,?,?,?,?
				)
			",
				$iMission,
				thisSecond(),
				$_SESSION['rid'],
				'change',
				addslashes($sTodo),
				$iGroup,
				$iUrgency,
				$iFinishTime,
				$sUsers,
				$iStatus
			);
			
			DataHandler::commit();
			
			return 1;
		}
		catch (Exception $e) {
			DataHandler::rollback();
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function updateWork($iMission)
	{
		try {
			$oSumQuery = DataHandler::query("
				SELECT SUM(duration)
				FROM work
				WHERE mission_id = ?
			", $iMission);

			list($iTotalwork) = $oSumQuery->fetch(PDO::FETCH_NUM);

			DataHandler::query("
				UPDATE missions
				SET work = ?
				WHERE id = ?
			", $iTotalwork, $iMission);

			return 1;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function getWork($iMissionID)
	{
		try {
			$oQuery = DataHandler::query("
				SELECT
					user_id,
					duration,
					timing,
					starttime
				FROM work
				WHERE mission_id = ?
				ORDER BY starttime DESC, timing DESC
			", $iMissionID);

			$oWork = array();
			while (list($iUser, $iDuration, $iTiming, $iStartTime) = $oQuery->fetch(PDO::FETCH_NUM))
			{
				$oWorkEntity = array();
				$oWorkEntity['iUser'] = $iUser;
				$oWorkEntity['iDuration'] = $iDuration;
				$oWorkEntity['iTiming'] = $iTiming;
				$oWorkEntity['iStartTime'] = $iStartTime;
				array_push($oWork, (object)$oWorkEntity);
			}
			return $oWork;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function getLog($iMissionID) {
		try {
			$oQuery = DataHandler::query("
				SELECT
					timing,
					user_id,
					actiontype,
					stat_todo,
					stat_group_id,
					stat_urgency_id,
					stat_finishtime,
					stat_users,
					stat_status
				FROM missionlog
				WHERE mission_id = ?
				ORDER BY timing DESC
			", $iMissionID);

			$oLog = array();
			while (list($iTiming, $iUser, $sActiontype, $sTodo, $iGroup, $iUrgency, $iFinishTime, $sUsers, $iStatus) = $oQuery->fetch(PDO::FETCH_NUM))
			{
				$oLogEntity = array();
				$oLogEntity['iTiming'] = $iTiming;
				$oLogEntity['iUser'] = $iUser;
				$oLogEntity['sActiontype'] = $sActiontype;
				$oLogEntity['sTodo'] = $sTodo;
				$oLogEntity['iGroup'] = $iGroup;
				$oLogEntity['iUrgency'] = $iUrgency;
				$oLogEntity['iFinishTime'] = $iFinishTime;
				$oLogEntity['sUsers'] = $sUsers;
				$oLogEntity['iStatus'] = $iStatus;
				array_push($oLog, (object)$oLogEntity);
			}
			
			return $oLog;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	// The statuses should be customizable in the future. Until then, this'll have to do.
	public static function getStatuses() {
		return JobHandler::getDefaultStatuses();
	}
	
	public static function changeMission($iJob, $iMissionID, $sTodo, $iMissiongroupID, $bAssign, $iStatus, $iUrgency, $iFinishTime, $iUsers, $iFiles) {
		
		DataHandler::beginTransaction();
		
		try {
			$oJobs = JobHandler::getJobs();
			$oJobConfig = $oJobs[$iJob]->getConfig();

			if (!is_array($iFiles)) {
				$iFiles = array();
			}

			if (!$oJobConfig['bAllowNogroupMissions'] && $iMissiongroupID == 0)
			{
				throw new MiJobException('Mission must be in a mission group (depends on config)');
			}

			if (!$oJobConfig['bAllowUserlessMissions'] && count($iUsers) == 0 && $bAssign)
			{
				throw new MiJobException('Userless missions not allowed (depends on config)');
			}
			$sUsers = (is_array($iUsers) ? implode('|', $iUsers) : '');

			if (!$sTodo)
			{
				throw new MiJobException('Task description must be provided');
			}

			if (stripslashes($sTodo) != stripslashes($oMission->sTodo) || $iMissiongroupID != $oMission->iGroup || $iUrgency != $oMission->iUrgency || $iFinishTime != $oMission->iFinishTime || $iStatus != $oMission->iStatus /* || $iUsers != $oMission->iUsers */ )
			{	
				DataHandler::query("
					INSERT INTO missionlog (
						mission_id,
						timing,
						user_id,
						actiontype,
						stat_todo,
						stat_group_id,
						stat_urgency_id,
						stat_finishtime,
						stat_users,
						stat_status
					) VALUES (
						?,?,?,?,?,?,?,?,?,?
					)
				",
					$iMissionID,
					thisSecond(),
					$_SESSION['rid'],
					'change',
					$sTodo,
					$iMissiongroupID,
					$iUrgency,
					$iFinishTime,
					$sUsers,
					$iStatus
				);
			}

			DataHandler::query("
				UPDATE missions
				SET
					todo = ?,
					status = ?,
					group_id = ?,
					urgency_id = ?,
					assigntime = ?,
					finishtime = ?,
					users = ?
				WHERE id = ?
			",
				$sTodo,
				$iStatus,
				$iMissiongroupID,
				$iUrgency,
				thisSecond(),
				$iFinishTime,
				$sUsers,
				$iMissionID
			);

			DataHandler::query("
				DELETE FROM missions_files
				WHERE mission_id = ?
			", $iMissionID);

			foreach ($iFiles as $iThisFile) {
				DataHandler::query("
					INSERT INTO missions_files (
						mission_id,
						file_id
					) VALUES (
						?,
						?
					)
				", $iMissionID, $iThisFile);
			}
			
			MissionHandler::fixFileCount($iMissionID);
			
			DataHandler::commit();
			
			return 1;
		}
		catch (Exception $e) {
			DataHandler::rollback();
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function fixFileCount($iMissionID) {
		try {
			$oCountQuery = DataHandler::query("
				SELECT COUNT(*)
				FROM missions_files
				WHERE mission_id = ?
			", $iMissionID);

			list($iCount) = $oCountQuery->fetch(PDO::FETCH_NUM);

			DataHandler::query("
				UPDATE missions
				SET file_count = ?
				WHERE id = ?
			", $iCount, $iMissionID);
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function addMission($iJob, $sTodo, $iRequester, $iMissiongroupID, $iStatus, $iUrgency, $iFinishTime, $iUsers, $iFiles)
	{
		DataHandler::beginTransaction();
		
		try {
			if (!is_array($iUsers)) {
				$iUsers = array();
			}

			if (!is_array($iFiles)) {
				$iFiles = array();
			}

			$oJobs = JobHandler::getJobs();
			$oJobConfig = $oJobs[$iJob]->getConfig();
			if (!$oJobConfig['bAllowNogroupMissions'] && $iMissiongroupID == 0) {
				throw new MiJobException('Mission must be in a mission group (depends on config)');
			}

			if (!@$oJobConfig['bAllowUserlessMissions'] && count($iUsers) == 0) {
				throw new MiJobException('Userless tasks not allowed (depends on config)');
			}

			if (!$sTodo) {
				throw new MiJobException('Task description is required');
			}
			
			$oQuery = DataHandler::query("
				INSERT INTO missions (
					todo,
					requester,
					group_id,
					request_id,
					job_id,
					status,
					urgency_id,
					assigntime,
					finishtime,
					users,
					requesttime,
					file_count
				) VALUES (
					?,?,?,?,?,?,?,?,?,?,?,?
				)
			",
				$sTodo,
				$iRequester,
				$iMissiongroupID,
				MissionHandler::generateRequestID(),
				$iJob,
				$iStatus,
				$iUrgency,
				thisSecond(),
				$iFinishTime,
				join('|', $iUsers),
				thisSecond(),
				count($iFiles)
			);

			$iNewID = DataHandler::lastInsertId();

			$oLogQuery = DataHandler::query("
				INSERT INTO missionlog (
					mission_id,
					timing,
					user_id,
					actiontype,
					stat_todo,
					stat_group_id,
					stat_urgency_id,
					stat_finishtime,
					stat_users,
					stat_status
				) VALUES (
					?,?,?,?,?,?,?,?,?,?
				)
			",
				$iNewID,
				thisSecond(),
				$_SESSION['rid'],
				'create',
				$sTodo,
				$iMissiongroupID,
				$iUrgency,
				$iFinishTime,
				implode('|', $iUsers),
				$iStatus
			);

			if (count($iFiles) > 0) {
				foreach ($iFiles as $iThisFile) {
					DataHandler::query("
						INSERT INTO missions_files (
							mission_id,
							file_id
						) VALUES (
							?,
							?
						)
					", $iNewID, $iThisFile);
				}
			}
			
			DataHandler::commit();
			
			return $iNewID;
		}
		catch (Exception $e) {
			DataHandler::rollback();
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function delMission($iJob, $iMissionID) {
		
		DataHandler::beginTransaction();

		try {
			
			DataHandler::query("
				DELETE FROM missions
				WHERE id = ?
			", $iMissionID);

			DataHandler::query("
				DELETE FROM notes
				WHERE mission_id = ?
			", $iMissionID);

			DataHandler::query("
				DELETE FROM work
				WHERE mission_id = ?
			", $iMissionID);

			DataHandler::query("
				DELETE FROM missionlog
				WHERE mission_id = ?
			", $iMissionID);

			DataHandler::query("
				DELETE FROM missions_files
				WHERE mission_id = ?
			", $iMissionID);

			DataHandler::commit();

			return 1;
		}
		catch (Exception $e) {
			DataHandler::rollback();
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	public static function getMissions($iJob, $bForceShowHidden = false) {
		try {
			if (@is_array($GLOBALS['mission']['missions'][$iJob])) {
				return $GLOBALS['mission']['missions'][$iJob];
			}
			
			$arrQueryParams = array();

			$sQueryString = "
				SELECT
					id,
					todo,
					status,
					requester,
					group_id,
					urgency_id,
					requesttime,
					assigntime,
					finishtime,
					request_id,
					users,
					work,
					note_count,
					file_count
				FROM missions
				WHERE job_id = ?
			";
			$arrQueryParams[] = $iJob;
			
			if (!@$_SESSION['oJobSettings'][$iJob]['showhiddenmissions'] && !$bForceShowHidden) {
				$oJobStatus = MissionHandler::getStatuses();
				$sQueryString .= "AND (";
				for ($i = 0; $i < count($oJobStatus); $i++) {
					if ($oJobStatus[$i]['visible']) {
						if ($i > 0) {
							$sQueryString .= "OR ";
						}
						$sQueryString .= "status = ? ";
						$arrQueryParams[] = $i;
					}
				}
				$sQueryString .= ")";
			}
			if (@$_SESSION['oJobSettings'][$iJob]['onlymissiongroup']) {
				$sQueryString .= "AND group_id = ? ";
				$arrQueryParams[] = $_SESSION['oJobSettings'][$iJob]['onlymissiongroup'];
			}

			switch (@$_SESSION['oJobSettings'][$iJob]['sortby']) {
				default:
					case 'urgency':
						$sQueryString .= " ORDER BY urgency_id";
						break;
					case 'status':
						$sQueryString .= " ORDER BY status DESC";
						break;
			}

			$oQuery = DataHandler::prepare($sQueryString);
			$oQuery->execute($arrQueryParams);

			$GLOBALS['mission']['missions'][$iJob] = array();
			while (list($iID, $sTodo, $iStatus, $iRequester, $iGroup, $iUrgency, $iRequestTime, $iAssignTime, $iFinishTime, $sRequestID, $sUsers, $iTotalwork, $iNoteCount, $iFileCount) = $oQuery->fetch()) {
				$iUserArray = ($sUsers ? split('\|', trim($sUsers, '|')) : array());
				$GLOBALS['mission']['missions'][$iJob][$iID] = new Mission($iID, $sTodo, $iStatus, $iRequester, $iGroup, $iUrgency, $iRequestTime, $iAssignTime, $iFinishTime, $sRequestID, $iUserArray, $iTotalwork, $iNoteCount, $iFileCount);
			}
			return $GLOBALS['mission']['missions'][$iJob];
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
	
	// Gets just one mission.
	// This public static function should be re-made to make its own database query.
	// However, if or when there'll be a decent cache mechanism for missions, it's good as it is.
	public static function getMission($iJob, $iMission) {
		$oMissions = MissionHandler::getMissions($iJob);
		return $oMissions[$iMission];
	}
	
	public static function generateRequestID()
	{
		try {
			$bOK = false;
			while (!$bOK) {
				$iRand = rand(1, 99999999);

				while (strlen($iRand) < 8)
					$iRand = '0'.$iRand;

				$oQuery = DataHandler::query("
					SELECT id
					FROM missions
					WHERE request_id = ?
				", $iRand);
				if ($oQuery->rowCount() == 0)
					$bOK = true;
				else
					$bOK = false;;
			}
			return $iRand;
		}
		catch (Exception $e) {
			ErrorHandler::addError($e->getMessage());
		}
	}
}
?>
